import { AgentMCPBridge, AgentConfig } from '../core/agent-mcp-bridge';
import { MCPClient } from '../core/mcp-client';

class MockMCPClient extends MCPClient {
  private mockTools = [
    {
      name: 'get_weather',
      description: 'Get weather information for a location',
      inputSchema: {
        type: 'object' as const,
        properties: {
          location: {
            type: 'string',
            description: 'The location to get weather for'
          }
        },
        required: ['location']
      }
    },
    {
      name: 'calculate',
      description: 'Perform mathematical calculations',
      inputSchema: {
        type: 'object' as const,
        properties: {
          expression: {
            type: 'string',
            description: 'Mathematical expression to evaluate'
          }
        },
        required: ['expression']
      }
    }
  ];

  private mockResources = [
    {
      uri: 'weather://beijing',
      name: 'Beijing Weather',
      description: 'Current weather information for Beijing'
    },
    {
      uri: 'weather://shanghai',
      name: 'Shanghai Weather',
      description: 'Current weather information for Shanghai'
    }
  ];

  async connect(): Promise<void> {
    console.log('Mock MCP Client connected');
    this.getConnection().isConnected = true;
    this.getConnection().capabilities = {
      tools: this.mockTools,
      resources: this.mockResources
    };
  }

  async callTool(toolName: string, arguments_: Record<string, any>): Promise<any> {
    console.log(`Mock tool call: ${toolName} with args:`, arguments_);
    
    switch (toolName) {
      case 'get_weather':
        return {
          location: arguments_.location,
          temperature: Math.floor(Math.random() * 30) + 10,
          condition: ['Sunny', 'Cloudy', 'Rainy'][Math.floor(Math.random() * 3)],
          humidity: Math.floor(Math.random() * 50) + 30
        };
        
      case 'calculate':
        try {
          const result = eval(arguments_.expression);
          return { expression: arguments_.expression, result };
        } catch (error) {
          return { error: 'Invalid expression', details: error instanceof Error ? error.message : 'Unknown error' };
        }
        
      default:
        throw new Error(`Unknown tool: ${toolName}`);
    }
  }

  async listTools(): Promise<any[]> {
    return this.mockTools;
  }

  async listResources(): Promise<any[]> {
    return this.mockResources;
  }

  async disconnect(): Promise<void> {
    console.log('Mock MCP Client disconnected');
    this.getConnection().isConnected = false;
  }

  getSentMessages(): any[] {
    return [];
  }
}

async function quickStartExample() {
  console.log('=== Quick Start Example ===');
  
  const agentConfig: AgentConfig = {
    name: 'QuickStartAgent',
    description: 'Quick start demo agent',
    systemPrompt: 'You are a helpful assistant that can use tools to help users.',
    mcpClients: [
      {
        serverUrl: 'ws://localhost:8080/mcp',
        timeout: 30000,
        retryCount: 3
      }
    ]
  };

  const agent = new AgentMCPBridge(agentConfig);
  
  try {
    console.log('Attempting to connect to MCP server...');
    console.log('Note: This will fail if no server is running at ws://localhost:8080/mcp');
    console.log('For a working demo, use: npm run dev mock-example');
    
    await agent.initialize();
    
    console.log('Agent initialized successfully!');
    console.log('Available tools:', agent.getAvailableTools().map(t => t.name));
    
    const demoConversation = [
      'Hi! Can you help me with some calculations?',
      'What\'s 25 * 4?',
      'Can you also check the weather in Beijing?',
      'Thank you! That\'s all I needed.'
    ];
    
    for (const userMessage of demoConversation) {
      console.log(`\nUser: ${userMessage}`);
      
      const response = await agent.processMessage({
        role: 'user',
        content: userMessage
      });
      
      console.log(`Assistant: ${response.content}`);
      
      await new Promise(resolve => setTimeout(resolve, 1500));
    }
    
  } catch (error) {
    console.log('Expected: Connection failed (no MCP server running)');
    console.log('This is normal if you don\'t have an MCP server running.');
    console.log('To run a working demo, try: npm run dev mock-example');
  } finally {
    await agent.shutdown();
  }
}

async function mockExample() {
  console.log('=== Mock Example (No Server Required) ===');
  
  const agentConfig: AgentConfig = {
    name: 'MockAgent',
    description: 'Mock agent using simulated MCP server',
    systemPrompt: 'You are a helpful assistant that can use tools to help users.',
    mcpClients: [
      {
        serverUrl: 'ws://localhost:9999/mock',
        timeout: 30000,
        retryCount: 1
      }
    ]
  };

  const agent = new AgentMCPBridge(agentConfig);
  
  try {
    console.log('This example uses a mock client that simulates MCP server responses...');
    
    // Manually inject mock client for demo
    const mockClient = new MockMCPClient({
      serverUrl: 'ws://localhost:9999/mock',
      timeout: 30000,
      retryCount: 1
    });
    
    await mockClient.connect();
    
    console.log('Mock client connected!');
    console.log('Available tools:', mockClient.getSentMessages().length > 0 ? 'Mock tools available' : 'No tools');
    
    const demoTools = [
      { name: 'get_weather', args: { location: 'Beijing' } },
      { name: 'calculate', args: { expression: '25 * 4' } }
    ];
    
    for (const tool of demoTools) {
      console.log(`\nCalling tool: ${tool.name} with args:`, tool.args);
      
      try {
        const result = await mockClient.callTool(tool.name, tool.args);
        console.log('Tool result:', result);
      } catch (error) {
        console.log('Tool call failed:', error instanceof Error ? error.message : 'Unknown error');
      }
      
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
    
    await mockClient.disconnect();
    console.log('Mock example completed successfully!');
    
  } catch (error) {
    console.error('Mock example failed:', error);
  }
}

async function interactiveExample() {
  console.log('=== Interactive Example ===');
  console.log('This example shows how to use the agent interactively');
  console.log('Available commands:');
  console.log('  "help" - Show available tools');
  console.log('  "status" - Show agent status');
  console.log('  "quit" - Exit the example');
  console.log('  Any other text will be processed as a message');
  console.log('');
  
  const agentConfig: AgentConfig = {
    name: 'InteractiveAgent',
    description: 'Interactive demo agent',
    systemPrompt: 'You are a helpful assistant. Be concise and helpful in your responses.',
    mcpClients: [
      {
        serverUrl: 'mock://interactive-server',
        timeout: 30000,
        retryCount: 3
      }
    ]
  };

  const agent = new AgentMCPBridge(agentConfig);
  
  try {
    await agent.initialize();
    
    const readline = require('readline');
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    });
    
    const askQuestion = (question: string): Promise<string> => {
      return new Promise(resolve => {
        rl.question(question, resolve);
      });
    };
    
    console.log('Agent initialized! Type your messages below:');
    console.log('----------------------------------------');
    
    while (true) {
      const input = await askQuestion('You: ');
      
      if (input.toLowerCase() === 'quit') {
        break;
      }
      
      if (input.toLowerCase() === 'help') {
        console.log('\nAvailable tools:');
        const tools = agent.getAvailableTools();
        tools.forEach(tool => {
          console.log(`  - ${tool.name}: ${tool.description}`);
        });
        console.log('');
        continue;
      }
      
      if (input.toLowerCase() === 'status') {
        console.log('\nAgent Status:', JSON.stringify(agent.getStatus(), null, 2));
        console.log('');
        continue;
      }
      
      const response = await agent.processMessage({
        role: 'user',
        content: input
      });
      
      console.log(`Assistant: ${response.content}\n`);
    }
    
    rl.close();
    
  } catch (error) {
    console.error('Interactive example failed:', error);
  } finally {
    await agent.shutdown();
  }
}

export { quickStartExample, interactiveExample, mockExample, MockMCPClient };

if (require.main === module) {
  console.log('Running quick start example...');
  quickStartExample().catch(console.error);
}